#include <Windows.h>
#include <TChar.h>
#include "CDNSmartPackageDownload.h"
#include "apppath.h"
#include "lib.h"
#include "filestream.h"
#include "pathname.h"
#include "pkg.h"
#include "dir.h"

// --------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------
//
// "static" methods & data used by Smart Package Download Class
//
// --------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------

static LPCTSTR MANIFEST_SECTION = _T("Manifest");
static const String INSTALLED = _T("installed");
static const String URL_SEP = _T("/");
static const String _INI = _T(".ini");
static const String _ZIP = _T(".zip");
static const String _CRC = _T(".crc");
const String CDNSmartPackageDownload::PACKAGELIST_INI = PACKAGELIST_INI_MACRO;


// --------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------
//
// Smart Package Download Class
//
// --------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------

CDNSmartPackageDownload::CDNSmartPackageDownload(PkgDwnldClient* pkgDwnldClient,
                                                 const String& cdnAddress,
                                                 const String& cdnPackageList,
                                                 const String& package_name)
{
    Init(pkgDwnldClient, NULL, cdnAddress, cdnPackageList, package_name);
}

CDNSmartPackageDownload::CDNSmartPackageDownload(PkgListClient* pkgListClient,
                                                 const String& cdnAddress, 
                                                 const String& cdnPackageList)
{
    Init(NULL, pkgListClient, cdnAddress,  cdnPackageList, String::emptyString);
}

// common initialization
void CDNSmartPackageDownload::Init(PkgDwnldClient* pkgDwnldClient,
                                   PkgListClient* pkgListClient,
                                   const String& cdnAddress, 
                                   const String& cdnPackageList,
                                   const String& package_name)
{
    ASSERT( (pkgDwnldClient  &&  pkgListClient == NULL  &&  package_name.getLength() > 0)  ||
            (pkgListClient  &&  pkgDwnldClient == NULL  &&  package_name.getLength() == 0) );

    m_cdnProgressHandler = new CDNProgressHandler(this);
    m_cdnPackageManager = new PackageManager(package_name);
    m_PkgDwnldClient = pkgDwnldClient;
    m_PkgListClient = pkgListClient;
    m_hDownloadThread = NULL;
    m_DownloadType = DWNLD_TYPE_SYNC;
    m_bPackageListChanged = false;
    m_cdnAddress = cdnAddress;
    m_PackageListINI = cdnPackageList;
    m_package = package_name;
    m_crcPackage = 0;
    m_bps = 0;
    m_bCancelled = 0;
    m_bytesIn = 0;
    m_total = 0;
    m_bytesRead = 0;
    m_begintime = INVALIDTIME;
    m_lasteventtime = INVALIDTIME;
    m_overalltime = INVALIDTIME;
    m_lasteventbyte = 0;
    for (int i = 0; i < _countof(m_lasteventbytes); i++)
    {
        m_lasteventbytes[i] = (uint32)-1;
    }
}

CDNSmartPackageDownload::~CDNSmartPackageDownload()
{
    // If the download thread was started, we must wait for it to complete before dying.
    if (m_hDownloadThread)
    {
        ::WaitForSingleObject(m_hDownloadThread,INFINITE);
        m_hDownloadThread = NULL;
    }

    delete m_cdnPackageManager;
    m_cdnPackageManager = NULL;

    delete m_cdnProgressHandler;
    m_cdnProgressHandler = NULL;
}

bool CDNSmartPackageDownload::start()
{
    return false;
}

uint32 CDNSmartPackageDownload::throughput()
{
    // NOTE: Currently it is not possible to throttle the download speed
	return m_bps;
}

void CDNSmartPackageDownload::throughput(uint32 bps)
{
    // NOTE: Currently it is not possible to throttle the download speed
    m_bps = bps;
}

// called to signal "stop downloading file(s)"
void CDNSmartPackageDownload::cancel()
{
    _T_DEBUGMSG((_T("CDNSmartPackageDownload::cancel() called\n")));
    ::InterlockedExchange(&m_bCancelled, 1);
}

bool CDNSmartPackageDownload::isCancelled() const
{
    return m_bCancelled != 0;
}
